(function (window) {
  // 传递进来的匿名函数 称作 excutor：执行器函数(同步)
  function Promise (excutor) {
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'

    // 将当前promise对象保存起来
    const _this = this
    // 给promise对象指定status属性，初始值为pending
    this.status = PENDING
    // 给promise对象指定一个用于存储结果数据的属性
    this.data = null
    // 每个元素的结果 {onResolved() {}, onRejected() {}}
    this.callbacks = []

    function resolve (vlaue) {
      // 如果当前状态不是pending 直接结束 因为只要执行一次改变状态的函数 状态就不可以被更改
      if (_this.status !== PENDING) return
      // 将状态改为 resolved
      _this.status = RESOLVED
      // 保存value数据
      _this.data = vlaue
      // 如果有待执行的callback函数，立即异步执行回调函数 onResolved
      // 回调函数可能并不会第一时间被绑定
      if (_this.callbacks.length > 0) {
        // 放入队列 因为then函数中的回调是个异步方法 为了保证代码执行顺序一致性
        setTimeout(() => {
          // callbacksObj 两个回调函数
          _this.callbacks.forEach(callbacksObj => {
            // 执行回调函数 还需要改变要返回的新的promise的状态
            callbacksObj.onResolved(vlaue)
          })
        })
      }

    }
    function reject (reason) {
      // 如果当前状态不是pending 直接结束
      if (_this.status !== PENDING) return
      // 将状态改为 rejected
      _this.status = REJECTED
      // 保存reason数据
      _this.data = reason
      // 如果有待执行的callback函数，立即异步执行回调函数 onRejected
      if (_this.callbacks.length > 0) {
        // 放入队列 因为then函数中的回调是个异步方法
        setTimeout(() => {
          // callbacksObj 两个回调函数
          _this.callbacks.forEach(callbacksObj => {
            callbacksObj.onRejected(reason)
          })
        })
      }
    }

    try {
      // 立即同步执行excutor
      excutor(resolve, reject)
    } catch (error) {
      // 如果执行器(使用者传入的回掉函数)抛出异常，promise对象变为rejected状态
      reject(error)
    }

  }

  /* 
  Promise上的原型方法
  */
  // 指定成功和失败的回调函数 返回一个新的promise对象  onResolved：成功的回调  onRejected：失败的回调
  Promise.prototype.then = function (onResolved, onRejected) {
    const _this = this

    // 对使用者传递的回调函数进行判断 同时 当不传函数时 我们要去指定一个默认值 
    // onRejected 不传的时候 我们需要把错误继续向下传递 错误穿透
    if (typeof onResolved !== 'function') {
      onResolved = value => value
    }
    if (typeof onRejected !== 'function') {
      onRejected = err => { throw err }
    }

    // 返回一个新的promise
    return new Promise((resolve, reject) => {
      // 定义：处理回调函数的调用与promise的状态的改变 把多次使用的代码拎出来
      function handle (callback) { // callback: 指定要执行哪一个回调函数 onResolved / onRejected
        try {
          let result = callback(_this.data)
          if (result instanceof Promise) {
            result.then(resolve, reject)
          } else {
            resolve(result)
          }
        } catch (error) {
          reject(error)
        }
      }

      // 当前状态为resolved
      if (_this.status === 'resolved') {
        // promise的then方法为异步方法 所以我们执行的时候 要构造成异步的
        setTimeout(() => {
          /* 
          返回的promise的结果由 onResolved / onRejected 执行结果所决定
            1：抛出异常，返回promise的结果为失败 reason为异常
            2：无异常返回一个结果
              1：返回的结果是一个promise 那么把这个promise的结果返回
              2： 返回一个普通值
           */
          // 把这部分单独拎出来 因为要多次使用
          /* 
          try {
            // 传递进来的成功的回调函数执行的结果
            let result = onResolved(_this.data)
            if(result instanceof Promise){ // 返回的结果是一个promise
              // 要得到promise的结果必须使用then方法调用 因为结果在then的回调函数中
              result.then(resolve, reject)
            } else { // 返回的不是promise，返回promise成功
              resolve(result)
            }
          } catch (error) {
            reject(error)
          } 
          */
          handle(onResolved)
        })
      } else if (_this.status === 'rejected') { // 当前promise的状态是rejected
        setTimeout(() => {
          handle(onRejected)
        })
      } else { // 当前promise的状态是pending
        // 当excutor执行器函数异步任务还没执行完毕 status还没做出更改 那么我们需要把绑定在then中的回调函数存储起来，以供status状态改变时 再去调用方法
        _this.callbacks.push({
          onResolved (value) {
            handle(onResolved)
          },
          onRejected (reason) {
            handle(onRejected)
          }
        })
      }
    })
  }

  // 指定失败的回调函数 返回一个新的promise对象
  Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
  }
  /* 
    Promise函数对象上的方法
  */
  // 返回一个指定结果的promise对象
  Promise.resolve = function (vlaue) {

  }

  // 返回一个指定reason的失败的promise
  Promise.reject = function (reason) {

  }

  // 返回一个promise，只有当所有的promise都成功时才成功，否则只要有一个失败的就失败
  Promise.all = function (promises) {

  }

  // 返回一个promise，其结果由第一个完成的promise决定
  Promise.reason = function (promises) {

  }


  window.Promise = Promise
})(window)